package view;

import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;

import battleModel.BattleModel;
import battleModel.Missile;
import battleModel.Tank;

@SuppressWarnings("serial")
public class BattleView extends MasterViewPanel {

	private BattleModel bm;
	private Tank player;

	private BufferedImage tileImage;

	private boolean waitToStart;
	private Rectangle battleWindow;
	private Map<Integer, String> optionMap;

	private AffineTransform mapAffine;
	private ArrayList<Missile> missiles;
	private Image missileImage;
	private float alpha;

	public BattleView(MasterView m, BattleModel bm) {
		super(m);

		this.bm = bm;
		this.player = bm.getPlayer();
		
		// Fade into the game, waits to start 
		waitToStart = true;					
		alpha = 0.2f;
		battleWindow = bm.getBattleWindow();

		setWindowSize();
		setUpLayout();
		scaleObjects();

		missiles = new ArrayList<Missile>();

		TankKeyLis key = new TankKeyLis();
		this.setFocusable(true);
		this.addKeyListener(key);

		MouseLis mouse = new MouseLis();
		this.setFocusable(true);
		this.addMouseListener(mouse);
		MouseMotionLis mouseMotion = new MouseMotionLis();
		this.addMouseMotionListener(mouseMotion);
	}

	private void setWindowSize() {
		m.setResizable(true);
		m.setSize(battleWindow.width, battleWindow.height);
		m.setLocation(0, 0);
		m.setResizable(false);
	}

	private void scaleObjects() {
		double xScale, yScale;
		xScale = (double) battleWindow.width / 1300;
		yScale = (double) battleWindow.height / 950;
		mapAffine = new AffineTransform();
		mapAffine.scale(xScale, yScale);

		player.scale(xScale, yScale);
	}

	private void setUpLayout() {
		this.setLayout(null);
		try {
			tileImage = ImageIO.read(new File("images/maps/newGrass.png"));
			missileImage = ImageIO.read(new File("images/tanks/missile.png"))
					.getSubimage(110, 0, 40, 20);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void pauseGame() {

		String[] options = getOptions();

		int choice = JOptionPane.showOptionDialog(null,
				"What would you like to do?",
				"Player Health: " + player.getHealth(),
				JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null,
				options, options[0]);

		processPauseChoice(choice);
	}

	private String[] getOptions() {

		optionMap = new HashMap<Integer, String>();
		String[] options = new String[3];

		options[0] = "Resume";
		optionMap.put(0, "Resume");
		options[1] = "Main Menu";
		optionMap.put(1, "Main Menu");
		options[2] = "Quit";
		optionMap.put(2, "Quit");

		return options;
	}

	private void processPauseChoice(int i) {
		// optionPane exit pressed
		if (i == -1)
			return;

		String choice = optionMap.get((Integer) i);

		// Applying the appropriate heal to the appropriate button push
		// on the pause pane.
		if (choice.equals("Main Menu")) {
			m.changeView(Views.MENU, bm);
			return;
		} else if (choice.equals("Quit")) {
			System.exit(0);
		}
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2D = (Graphics2D) g;

		

		

		g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));
		g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

		g2D.drawImage(tileImage, mapAffine, null);
		g2D.drawImage(player.getTankImage(), player.getTankAffine(), null);
		g2D.drawImage(player.getTurretImage(), player.getTurretAffine(), null);
		
		for (Missile mis : missiles)
			g2D.drawImage(mis.getImage(), mis.getAffine(), null);

		if (waitToStart) {
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				waitToStart = false;
			}
		}

		alpha += 0.03f;
		if (alpha >= 1.0f) {
			alpha = 1.0f;
			// finishFade = true;
		} else {
			repaint();
		}

		// sleep for a bit

		try {
			Thread.sleep(5);
		} catch (InterruptedException e) {

			e.printStackTrace();
		}

	}

	private class TankKeyLis implements KeyListener {

		/**
		 * unless user presses 'p' for pause the keyEvent is sent to the battle
		 * model
		 */
		@Override
		public void keyPressed(KeyEvent e) {

			if (e.getKeyCode() == KeyEvent.VK_P) {
				pauseGame();
			} else if (bm.keyPressed(e))
				repaint();
		}

		@Override
		public void keyReleased(KeyEvent e) {
		}

		@Override
		public void keyTyped(KeyEvent e) {
		}

	}

	private class MouseLis implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent arg0) {
			Missile missile = new Missile(missileImage,
					player.getTurretAngle(), player.getTurretAffine());
			missile.getAffine().scale((double) battleWindow.width / 1300,
					(double) battleWindow.height / 950);
			missiles.add(missile);

			repaint();
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
		}

		@Override
		public void mousePressed(MouseEvent arg0) {
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
		}

	}

	private class MouseMotionLis implements MouseMotionListener {

		@Override
		public void mouseDragged(MouseEvent arg0) {
		}

		@Override
		public void mouseMoved(MouseEvent e) {
			player.adjustTurretFromMouse(e);
			repaint();
		}

	}
}
